﻿using System.Collections.Generic;

namespace AgLux
{
    /// <summary>
    /// Represents a tree structure of Section objects.
    /// </summary>

    public class Structure
    {
        private List<Section> _rootSections;
        private List<int> _currentSequence;

        /// <summary>
        /// Initializes a new instance of the Structure class.
        /// </summary>

        /// <param name="rootSections">
        /// The list of first level sections.
        /// </param>

        public Structure(List<Section> rootSections)
        {
            if (rootSections == null)
            {
                _rootSections = new List<Section>();
            }

            else
            {
                _rootSections = rootSections;
            }

            _currentSequence = new List<int>();
        }

        /// <summary>
        /// Gets the current section headline.
        /// </summary>

        public string CurrentHeadline
        {
            get
            {
                string currentSequence = "";

                foreach (int number in _currentSequence)
                {
                    currentSequence += number + 1 + ".";
                }

                currentSequence += " " + Section(_currentSequence).Headline;

                return currentSequence;
            }
        }

        /// <summary>
        /// Gets and sets the current section.
        /// </summary>

        public Section CurrentSection
        {
            get
            {
                return Section(_currentSequence);
            }
        }

        /// <summary>
        /// Gets and sets a specific section.
        /// </summary>

        /// <param name="numberSequence">
        /// The section number sequence.
        /// </param>

        /// <returns>
        /// The specific section.
        /// </returns>

        public Section Section(int[] numberSequence)
        {
            List<int> sequence = new List<int>();

            foreach (int number in numberSequence)
            {
                sequence.Add(number - 1);
            }

            return Section(sequence);
        }

        /// <summary>
        /// Gets and sets the first section in the structure.
        /// </summary>

        /// <returns>
        /// The first section.
        /// </returns>

        public Section FirstSection()
        {
            _currentSequence.Clear();

            return NextSection();
        }

        /// <summary>
        /// Gets and sets the next section in the structure.
        /// </summary>

        /// <returns>
        /// The next section.
        /// </returns>

        public Section NextSection()
        {
            List<int> sequence = _currentSequence;

            sequence.Add(0);

            if (Section(sequence) == null)
            {
                sequence = _currentSequence;
                sequence[sequence.Count - 1]++;
            }

            while (Section(sequence) == null && sequence.Count > 1)
            {
                sequence.RemoveAt(sequence.Count - 1);
                sequence[sequence.Count - 1]++;
            }

            return Section(sequence);
        }

        /// <summary>
        /// Gets and sets the previous section in the structure.
        /// </summary>

        /// <returns>
        /// The previous section.
        /// </returns>

        public Section PreviousSection()
        {
            List<int> sequence = _currentSequence;

            sequence[sequence.Count - 1]--;

            if (Section(sequence) == null)
            {
                sequence.RemoveAt(sequence.Count - 1);
            }

            else
            {
                while (Section(sequence) != null)
                {
                    sequence.Add(0);

                    if (Section(sequence) != null)
                    {
                        while (Section(sequence) != null)
                        {
                            sequence[sequence.Count - 1]++;
                        }

                        sequence[sequence.Count - 1]--;
                    }
                }

                sequence.RemoveAt(sequence.Count - 1);
            }

            return Section(sequence);
        }

        /// <summary>
        /// Gets the structure content.
        /// </summary>

        /// <param name="includeComponents">
        /// Whether the section components should be included.
        /// </param>

        /// <returns>
        /// The structure content.
        /// </returns>

        public string PrintContent(bool includeComponents)
        {
            List<int> sequence = new List<int>();
            sequence.Add(0);

            string content = "";

            foreach (Section section in _rootSections)
            {
                content += section.PrintContent(sequence, includeComponents);
                sequence[0]++;
            }

            return content;
        }

        /// <summary>
        /// Gets a specific section.
        /// </summary>

        /// <param name="numberSequence">
        /// The section number sequence.
        /// </param>

        /// <returns>
        /// The specific section.
        /// </returns>

        private Section Section(List<int> sequence)
        {
            Section section = null;
            List<Section> sections = _rootSections;

            for (int i = 0; i < sequence.Count; i++)
            {
                if (i > 0)
                {
                    sections = section.Sections;
                }

                if (sequence[i] >= 0 && sequence[i] < sections.Count)
                {
                    section = sections[sequence[i]];
                }

                else
                {
                    section = null;
                    i = sequence.Count;
                }
            }

            if (section != null)
            {
                _currentSequence = sequence;
            }

            return section;
        }
    }
}
